console.log('draw start')
const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
const width = canvas.width = window.innerWidth
|| document.documentElement.clientWidth
|| document.body.clientWidth;
const height = canvas.height = window.innerHeight
|| document.documentElement.clientHeight
|| document.body.clientHeight;
const span = document.querySelector('p#ball span')
const redSpan = document.querySelector('p#red span')
const blueSpan = document.querySelector('p#blue span')
function random(min, max) {
  return Math.floor(Math.random() * (max - min) + min)
}

function randomColor() {
  return `rgb(${random(0, 255)},${random(0, 255)},${random(0, 255)})`
}
/** 
 * 形状类
 * @param {number} x 初始横坐标
 * @param {number} y 初始纵坐标
 * @param {number} velX 水平速度
 * @param {number} velY 竖直速度
 */
class Shape{
  constructor(x, y, velX, velY) {
    this.x = x;
    this.y = y;
    this.velX = velX;
    this.velY = velY;
  }
}

/**
 * 小球类, 继承自Shape
 * @param {string} color 颜色
 * @param {number} size 大小
 */
class Ball extends Shape{
  constructor(x, y, velX, velY, color, size) {
    super(x, y, velX, velY)
    this.color = color;
    this.size = size;
  }
  /**
   * 绘制小球
   */
  draw() {
    ctx.beginPath();
    ctx.fillStyle = this.color;
    ctx.arc(this.x, this.y, this.size, 0, 2 * Math.PI);
    ctx.fill()
  }
  /**
   * 改变小球位置, 每次重绘位置改变
   */
  update() {
    // 当小球碰到边缘,反转小球的速度方向,向反方向移动
    if ((this.x + this.size) >= width) {
      this.velX = -(this.velX);
    }
    if ((this.x - this.size) <= 0) {
      this.velX = -(this.velX);
    }
    if ((this.y + this.size) >= height) {
      this.velY = -(this.velY);
    }
    if ((this.y - this.size) <= 0) {
      this.velY = -(this.velY);
    }
  
    this.x += this.velX;
    this.y += this.velY
  }
  /**
   * 碰撞检测, 当两个球碰撞时, 均更改颜色
   */
  collisionDetect() {
    for (let j = 0; j < balls.length; j++) {
      if (this !== balls[j]) {
        /**
         * 圆心距离:
         * 已知两个圆心点分别为(this.x,this.y) (balls[j].x,balls[j].y)
         * d^2 = (this.x - balls[j])^2 + (this.y - balls[j].y)^2
         */
        const dx = this.x - balls[j].x;
        const dy = this.y - balls[j].y;
        const distance = Math.sqrt(dx * dx + dy * dy);
        // 两个小球的中心距离如果小于两个小球的半径之和, 说明两小球碰撞, 同时版色
        if (distance < this.size + balls[j].size) {
          balls[j].color = this.color = randomColor();
        }
      }
    }
  }
}

/**
 * 恶魔圈类, 继承自Shape
 */
class EvilCircle extends Shape {
  constructor(x,y,color,type,grade) {
    super(x,y,20,20)
    this.color = color;
    this.size = 10
    this.type = type
    this.grade = grade
  }
  draw() {
    ctx.beginPath();
    ctx.strokeStyle = this.color;
    ctx.arc(this.x, this.y, this.size, 0, 2 * Math.PI);
    ctx.stroke()
  }
  /**
   * 恶魔圈边界检测, 当恶魔圈移动到边界时不需要向反方向移动, 回弹一定距离即可
   */
  checkBounds() {
    if ((this.x + this.size) >= width) {
      this.x -= 5
    }
    if ((this.x - this.size) <= 0) {
      this.x += 5
    }
    if ((this.y + this.size) >= height) {
      this.y -= 5
    }
    if ((this.y - this.size) <= 0) {
      this.y += 5
    }
  }
  /**
   * 恶魔圈移动方法, 由于更改为两个小球, onkeydown事件写在外面, 监听用户按下的按键, 执行对应恶魔圈的按键移动
   * @param {*} e 
   */
  setControls(e) {
    if (this.type==1) {
      switch(e.key) {
        case 'a':
          this.x -= this.velX;
          break;
        case 'd':
          this.x += this.velX;
          break;
        case 'w':
          this.y -= this.velY;
          break;
        case 's':
          this.y += this.velY;
          break;
      }
    } else {
      switch(e.key) {
        case 'ArrowLeft':
          this.x -= this.velX;
          break;
        case 'ArrowRight':
          this.x += this.velX;
          break;
        case 'ArrowUp':
          this.y -= this.velY;
          break;
        case 'ArrowDown':
          this.y += this.velY;
          break;
      }
    }
    
    // window.onmousemove = e => {
    //   this.x = e.offsetX;
    //   this.y = e.offsetY;
    // }
  }
  /**
   * 碰撞检测,当恶魔圈碰到小球后, 移除小球, 并给对应的恶魔圈计分
   */
  collisionDetect() {
    for (let j = 0; j < balls.length; j++) {
      /**
       * 圆心距离:
       * 已知两个圆心点分别为(this.x,this.y) (balls[j].x,balls[j].y)
       * d^2 = (this.x - balls[j])^2 + (this.y - balls[j].y)^2
       */
      const dx = this.x - balls[j].x;
      const dy = this.y - balls[j].y;
      const distance = Math.sqrt(dx * dx + dy * dy);
      // 两个小球的中心距离如果小于两个小球的半径之和, 说明被恶魔圈捕获, 移除小球
      if (distance < this.size + balls[j].size) {
        balls.splice(j,1)
        this.grade++;
        if (this.type==1) {
          redSpan.innerHTML = this.grade;
        }else {
          blueSpan.innerHTML = this.grade
        }
      }
    }
  }
}

let evil = new EvilCircle(width/2-20,height/2,'red',1,0)
let evil2 = new EvilCircle(width/2+20,height/2,'blue',2,0)
window.onkeydown = e => {
  if (e.key=='a'||e.key=='d'||e.key=='w'||e.key=='s') {
    evil.setControls(e)
  } else if(e.key=='ArrowLeft'||e.key=='ArrowRight'||e.key=='ArrowUp'||e.key=='ArrowDown'){
    evil2.setControls(e)
  }
}
let balls = []
// 循环小球数量, 为方便判断胜负, 此处应该是奇数个
while (balls.length < 25) {
  let size = random(10, 20);
  let ball = new Ball(
    random(0 + size, width - size),
    random(0 + size, height - size), 
    random(-7, 7), 
    random(-7, 7), 
    randomColor(), 
    size)
  balls.push(ball)
}


function loop() {
  // 每次移动重新覆盖画布颜色, 透明度可实现影子效果
  ctx.fillStyle = 'rgba(0,0,0,.80)';
  ctx.fillRect(0, 0, width, height);
  // testBall.draw();
  // testBall.update();
  let num = 0
  for (let i = 0; i < balls.length; i++) {
    balls[i].draw();
    balls[i].update();
    balls[i].collisionDetect()
    num++;
    // if(balls[i].exists) {
    // }
  }
  span.innerHTML = num
  evil.draw();
  evil.checkBounds()
  evil.collisionDetect()
  evil2.draw();
  evil2.checkBounds()
  evil2.collisionDetect()
  if(num==0) {
    let r = confirm(`${evil.grade>evil2.grade?'RED':'BLUE'} Evil Circle WIN! New Game?`);
    if (r==true) {
      location.reload()
    }
  } else {
    requestAnimationFrame(loop)
  }
}

loop()

console.log("draw end")